#target illustrator

// 显示对话框获取自定义值 a、b 和排序方式
var dialog = new Window("dialog", "输入序号参数");
dialog.orientation = "column";
dialog.alignChildren = ["fill", "fill"];

// 创建输入框
var aGroup = dialog.add("group");
aGroup.add("statictext", undefined, "起始值 (a):");
var aInput = aGroup.add("edittext", undefined, "1");
aInput.characters = 10;

var bGroup = dialog.add("group");
bGroup.add("statictext", undefined, "增量 (b):");
var bInput = bGroup.add("edittext", undefined, "1");
bInput.characters = 10;

// 创建排序方式选择框
var sortGroup = dialog.add("group");
sortGroup.add("statictext", undefined, "排序方式:");
var sortDropdown = sortGroup.add("dropdownlist", undefined, [
    "y值升序 (从上到下)",
    "y值降序 (从下到上)",
    "x值升序 (从左到右)",
    "x值降序 (从右到左)",
    "沿路径排序 (需先选择路径)",
    "沿路径反向排序 (需先选择路径)"
]);
sortDropdown.selection = 0; // 默认选择第一个选项

// 创建删除路径选项框
var deletePathGroup = dialog.add("group");
deletePathGroup.add("statictext", undefined, "完成后删除参考路径:");
var deletePathCheckbox = deletePathGroup.add("checkbox", undefined, "");
deletePathCheckbox.value = false; // 默认不删除路径

// 创建按钮组
var buttonGroup = dialog.add("group");
buttonGroup.alignment = "center";
var okButton = buttonGroup.add("button", undefined, "确定");
var cancelButton = buttonGroup.add("button", undefined, "取消");

// 处理按钮事件
okButton.onClick = function() {
    dialog.close(1);
};

cancelButton.onClick = function() {
    dialog.close(0);
};

// 显示对话框并等待用户输入
var result = dialog.show();

// 如果用户点击取消，则退出脚本
if (result === 0) {
    exit();
}

// 获取用户输入的值
var a = parseInt(aInput.text);
var b = parseInt(bInput.text);
var sortType = sortDropdown.selection.index; // 0-3: 原有排序方式, 4: 沿路径排序, 5: 沿路径反向排序
var deletePath = deletePathCheckbox.value; // 是否删除参考路径

// 验证输入是否为有效数字
if (isNaN(a) || isNaN(b)) {
    alert("请输入有效的数字！");
    exit();
}

// 获取当前文档
if (app.documents.length === 0) {
    alert("请先打开一个文档！");
    exit();
}

var doc = app.activeDocument;

// 获取选中的项目
if (doc.selection.length === 0) {
    alert("请先选择一些文本对象！");
    exit();
}

// 如果选择了沿路径排序，需要选择路径
var pathItem = null;
if (sortType === 4 || sortType === 5) {
    // 查找选中的路径对象
    for (var i = 0; i < doc.selection.length; i++) {
        if (doc.selection[i].typename === "PathItem") {
            pathItem = doc.selection[i];
            break;
        }
    }
    
    if (!pathItem) {
        alert("沿路径排序需要选择一个路径对象！");
        exit();
    }
}

// 递归函数：查找所有文本对象
function findAllTextItems(item, textItems) {
    // 检查是否为文本框架（点文本、路径文本、区域文本）
    if (item.typename === "TextFrame") {
        // 获取文本框架的中心点坐标
        var bounds = item.geometricBounds;
        var xPosition = (bounds[0] + bounds[2]) / 2; // 中心点 x 坐标
        var yPosition = (bounds[1] + bounds[3]) / 2; // 中心点 y 坐标
        textItems.push({
            item: item,
            x: xPosition,
            y: yPosition
        });
    }
    // 如果是编组，递归查找其中的文本对象
    else if (item.typename === "GroupItem") {
        for (var i = 0; i < item.pageItems.length; i++) {
            findAllTextItems(item.pageItems[i], textItems);
        }
    }
    // 如果是图层，递归查找其中的文本对象
    else if (item.typename === "Layer") {
        for (var i = 0; i < item.pageItems.length; i++) {
            findAllTextItems(item.pageItems[i], textItems);
        }
    }
}

// 筛选出文本对象
var textItems = [];

// 如果是沿路径排序，需要排除路径对象
if (sortType === 4 || sortType === 5) {
    for (var i = 0; i < doc.selection.length; i++) {
        if (doc.selection[i] !== pathItem) {
            findAllTextItems(doc.selection[i], textItems);
        }
    }
} else {
    for (var i = 0; i < doc.selection.length; i++) {
        findAllTextItems(doc.selection[i], textItems);
    }
}

// 如果没有选中文本对象
if (textItems.length === 0) {
    alert("请选择至少一个文本对象！");
    exit();
}

// 根据用户选择的排序方式排序
switch (sortType) {
    case 0: // y值升序 (从上到下)
        textItems.sort(function(a, b) {
            return b.y - a.y;
        });
        break;
    case 1: // y值降序 (从下到上)
        textItems.sort(function(a, b) {
            return a.y - b.y;
        });
        break;
    case 2: // x值升序 (从左到右)
        textItems.sort(function(a, b) {
            return a.x - b.x;
        });
        break;
    case 3: // x值降序 (从右到左)
        textItems.sort(function(a, b) {
            return b.x - a.x;
        });
        break;
    case 4: // 沿路径排序
        // 为每个文本对象计算到路径的距离和路径上的位置
        for (var i = 0; i < textItems.length; i++) {
            var textItem = textItems[i];
            var pointOnPath = getClosestPointOnPath(textItem.x, textItem.y, pathItem);
            textItem.pathPosition = pointOnPath.position;
        }
        
        // 按路径位置排序
        textItems.sort(function(a, b) {
            return a.pathPosition - b.pathPosition;
        });
        break;
    case 5: // 沿路径反向排序
        // 为每个文本对象计算到路径的距离和路径上的位置
        for (var i = 0; i < textItems.length; i++) {
            var textItem = textItems[i];
            var pointOnPath = getClosestPointOnPath(textItem.x, textItem.y, pathItem);
            textItem.pathPosition = pointOnPath.position;
        }
        
        // 按路径位置排序
        textItems.sort(function(a, b) {
            return a.pathPosition - b.pathPosition;
        });
        
        // 反转数组以实现反向排序
        textItems.reverse();
        break;
}

// 计算点到路径的最近投影点
function getClosestPointOnPath(x, y, path) {
    var minDistance = Number.MAX_VALUE;
    var closestPosition = 0;
    var totalLength = 0;
    
    // 获取路径的所有路径点
    var pathPoints = path.pathPoints;
    if (pathPoints.length > 0) {
        // 遍历每一段路径（线段或贝塞尔曲线）
        for (var i = 0; i < pathPoints.length - 1; i++) {
            var startPoint = pathPoints[i].anchor;
            var endPoint = pathPoints[i + 1].anchor;
            
            // 获取控制点
            var startRightDirection = pathPoints[i].rightDirection;
            var endLeftDirection = pathPoints[i + 1].leftDirection;
            
            // 检查是否为直线段
            var isStraight = (startPoint[0] == startRightDirection[0] && startPoint[1] == startRightDirection[1]) &&
                            (endPoint[0] == endLeftDirection[0] && endPoint[1] == endLeftDirection[1]);
            
            // 计算这一段的近似长度
            var segmentLength = 0;
            if (isStraight) {
                // 直线段
                segmentLength = Math.sqrt(Math.pow(endPoint[0] - startPoint[0], 2) + Math.pow(endPoint[1] - startPoint[1], 2));
            } else {
                // 贝塞尔曲线段，使用近似长度计算
                segmentLength = getBezierCurveLength(startPoint, startRightDirection, endLeftDirection, endPoint);
            }
            
            // 在这一段上找到最近点
            var closestInfo = getClosestPointOnSegment(x, y, startPoint, endPoint, startRightDirection, endLeftDirection, isStraight);
            if (closestInfo.distance < minDistance) {
                minDistance = closestInfo.distance;
                closestPosition = totalLength + closestInfo.position * segmentLength;
            }
            
            totalLength += segmentLength;
        }
    }
    
    return {
        position: closestPosition
    };
}

// 计算点到线段或贝塞尔曲线的最近点
function getClosestPointOnSegment(x, y, startPoint, endPoint, startRightDirection, endLeftDirection, isStraight) {
    var minDistance = Number.MAX_VALUE;
    var bestPosition = 0;
    
    // 在线段上采样多个点来近似计算最近点
    var samples = 50;
    for (var i = 0; i <= samples; i++) {
        var t = i / samples;
        var point;
        
        if (isStraight) {
            // 直线段插值
            point = [
                startPoint[0] + t * (endPoint[0] - startPoint[0]),
                startPoint[1] + t * (endPoint[1] - startPoint[1])
            ];
        } else {
            // 贝塞尔曲线插值
            point = getBezierPoint(t, startPoint, startRightDirection, endLeftDirection, endPoint);
        }
        
        var distance = Math.sqrt(Math.pow(point[0] - x, 2) + Math.pow(point[1] - y, 2));
        if (distance < minDistance) {
            minDistance = distance;
            bestPosition = t;
        }
    }
    
    return {
        distance: minDistance,
        position: bestPosition
    };
}

// 计算贝塞尔曲线上的点
function getBezierPoint(t, p0, p1, p2, p3) {
    var cx = 3 * (p1[0] - p0[0]);
    var bx = 3 * (p2[0] - p1[0]) - cx;
    var ax = p3[0] - p0[0] - cx - bx;
    
    var cy = 3 * (p1[1] - p0[1]);
    var by = 3 * (p2[1] - p1[1]) - cy;
    var ay = p3[1] - p0[1] - cy - by;
    
    var tSquared = t * t;
    var tCubed = tSquared * t;
    
    return [
        (ax * tCubed) + (bx * tSquared) + (cx * t) + p0[0],
        (ay * tCubed) + (by * tSquared) + (cy * t) + p0[1]
    ];
}

// 计算贝塞尔曲线的近似长度
function getBezierCurveLength(p0, p1, p2, p3) {
    // 使用数值积分近似计算曲线长度
    var length = 0;
    var steps = 100;
    var prevPoint = p0;
    
    for (var i = 1; i <= steps; i++) {
        var t = i / steps;
        var point = getBezierPoint(t, p0, p1, p2, p3);
        length += Math.sqrt(Math.pow(point[0] - prevPoint[0], 2) + Math.pow(point[1] - prevPoint[1], 2));
        prevPoint = point;
    }
    
    return length;
}

// 替换文本内容
for (var i = 0; i < textItems.length; i++) {
    var currentValue = a + i * b;
    textItems[i].item.contents = currentValue.toString();
}

// 如果用户选择了删除参考路径，则删除它
if (deletePath && pathItem) {
    pathItem.remove();
}

alert("已完成！已处理 " + textItems.length + " 个文本对象。" + (deletePath && pathItem ? " 参考路径已删除。" : ""));
